home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Networking / MoreAutoPush / MoreOpenTransport / MoreAutoPush.c next >
Encoding:
Text File  |  2000-10-06  |  11.3 KB  |  381 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        MoreAutoPush.c
  3.  
  4.     Contains:    A simple framework for doing autopush properly.
  5.  
  6.     Written by: Quinn "The Eskimo!"
  7.  
  8.     Copyright:    Copyright © 1997-2000 by Apple Computer, Inc., All Rights Reserved.
  9.  
  10.     Disclaimer:    IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
  11.                 ("Apple") in consideration of your agreement to the following terms, and your
  12.                 use, installation, modification or redistribution of this Apple software
  13.                 constitutes acceptance of these terms.  If you do not agree with these terms,
  14.                 please do not use, install, modify or redistribute this Apple software.
  15.  
  16.                 In consideration of your agreement to abide by the following terms, and subject
  17.                 to these terms, Apple grants you a personal, non-exclusive license, under Apple’s
  18.                 copyrights in this original Apple software (the "Apple Software"), to use,
  19.                 reproduce, modify and redistribute the Apple Software, with or without
  20.                 modifications, in source and/or binary forms; provided that if you redistribute
  21.                 the Apple Software in its entirety and without modifications, you must retain
  22.                 this notice and the following text and disclaimers in all such redistributions of
  23.                 the Apple Software.  Neither the name, trademarks, service marks or logos of
  24.                 Apple Computer, Inc. may be used to endorse or promote products derived from the
  25.                 Apple Software without specific prior written permission from Apple.  Except as
  26.                 expressly stated in this notice, no other rights or licenses, express or implied,
  27.                 are granted by Apple herein, including but not limited to any patent rights that
  28.                 may be infringed by your derivative works or by other works in which the Apple
  29.                 Software may be incorporated.
  30.  
  31.                 The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
  32.                 WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
  33.                 WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  34.                 PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
  35.                 COMBINATION WITH YOUR PRODUCTS.
  36.  
  37.                 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
  38.                 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  39.                 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  40.                 ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
  41.                 OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
  42.                 (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
  43.                 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  44.  
  45.     Change History (most recent first):
  46.  
  47.          <1>     5/10/00    Quinn   First checked in.
  48. */
  49.  
  50. /////////////////////////////////////////////////////////////////////
  51.  
  52. // MIB Setup
  53.  
  54. #include "MoreSetup.h"
  55.  
  56. // Mac OS Interfaces
  57.  
  58. // Our prototypes
  59.  
  60. #include "MoreAutoPush.h"
  61.  
  62. /////////////////////////////////////////////////////////////////////
  63. #pragma mark ----- AutoPush Utilities -----
  64.  
  65. static int FindModule(const char *moduleName, OTAutopushInfo *autoPushInfo)
  66.     // Searches the sap_list of autoPushInfo for moduleName and returns
  67.     // the index of it into the list of the module name.  Returns -1 if the
  68.     // module isn't in the list. 
  69. {
  70.     Boolean found;
  71.     ItemCount moduleIndex;
  72.  
  73.     moduleIndex = 0;
  74.     found = false;
  75.     while ( ! found && moduleIndex < autoPushInfo->sap_npush ) {
  76.         found = OTStrEqual(moduleName, autoPushInfo->sap_list[moduleIndex]);
  77.         if ( ! found ) {
  78.             moduleIndex += 1;
  79.         }
  80.     }
  81.     if ( ! found ) {
  82.         moduleIndex = -1;
  83.     }
  84.     return moduleIndex;
  85. }
  86.  
  87. static void SetupAutopush(OTAutopushInfo *autoPushInfo, UInt32 command, const char *driverName)
  88.     // Sets up autoPushInfo for a command.    Sets the sap_cmd, sap_device_name,
  89.     // sap_minor, and sap_lastminor fields.     The callee is responsible
  90.     // for setting up the sap_npush and sap_list fields.
  91. {
  92.     autoPushInfo->sap_cmd = command;
  93.     OTStrCopy(autoPushInfo->sap_device_name, driverName);
  94.     autoPushInfo->sap_minor = 0;
  95.     autoPushInfo->sap_lastminor = 0;
  96. }
  97.  
  98. static void SetupIoctl(struct strioctl *ioctlInfo, UInt32 command, OTAutopushInfo *autoPushInfo)
  99.     // Sets up ioctlInfo for an autopush command.
  100. {
  101.     ioctlInfo->ic_cmd = command;
  102.     ioctlInfo->ic_dp  = (char *) autoPushInfo;
  103.     ioctlInfo->ic_len = sizeof(OTAutopushInfo);
  104.     ioctlInfo->ic_timout = INFTIM;
  105. }
  106.  
  107. /////////////////////////////////////////////////////////////////////
  108. #pragma mark ----- AutoPush Primitives -----
  109.  
  110. static OSStatus SadGet(StreamRef sadStream, OTAutopushInfo *autoPushInfo, const char *driverName)
  111.     // Given a connection to the "sad" module, get the autopush information
  112.     // for the driver and return it in autoPushInfo.  Only the sap_npush and
  113.     // sap_list fields of autoPushInfo are guaranteed to be valid upon return.
  114. {
  115.     OSStatus err;
  116.     struct strioctl ioctlInfo;
  117.  
  118.     SetupAutopush(autoPushInfo, kSAP_ALL, driverName);
  119.     autoPushInfo->sap_npush = kOTAutopushMax;
  120.  
  121.     SetupIoctl(&ioctlInfo, I_SAD_GAP, autoPushInfo);
  122.     
  123.     err = OTStreamIoctl(sadStream, I_STR, (void*)&ioctlInfo);
  124.     if (err == kENODEVErr) {
  125.  
  126.         // Handle the case where there is no autopush information
  127.         // set for driverName by returning an empty list of modules.
  128.         
  129.         autoPushInfo->sap_npush = 0;
  130.         err = noErr;
  131.     }
  132.  
  133.     return err;
  134. }
  135.  
  136. static OSStatus SadSet(StreamRef sadStream, OTAutopushInfo *autoPushInfo, const char *driverName)
  137.     // Given a connection to the "sad" module, set the autopush information
  138.     // for the driver to autoPushInfo.    Assumes that there is no autopush info
  139.     // set for the driver at the moment.  Only takes heed of the sap_npush and 
  140.     // sap_list fields of autoPushInfo.
  141. {
  142.     OSStatus err;
  143.     struct strioctl ioctlInfo;
  144.  
  145.     SetupAutopush(autoPushInfo, kSAP_ALL, driverName);
  146.     SetupIoctl(&ioctlInfo, I_SAD_SAP, autoPushInfo);
  147.     
  148.     err = OTStreamIoctl(sadStream, I_STR, (void*)&ioctlInfo);
  149.  
  150.     return err;
  151. }
  152.  
  153. static OSStatus SadClear(StreamRef sadStream, const char *driverName)
  154.     // Given a connection to the "sad" module, clear the autopush information
  155.     // for the driver.
  156. {
  157.     OSStatus err;
  158.     OTAutopushInfo clearAutoPushInfo;
  159.     struct strioctl ioctlInfo;
  160.  
  161.     SetupAutopush(&clearAutoPushInfo, kSAP_CLEAR, driverName);
  162.     clearAutoPushInfo.sap_npush = 0;
  163.     SetupIoctl(&ioctlInfo, I_SAD_SAP, &clearAutoPushInfo);
  164.     
  165.     err = OTStreamIoctl(sadStream, I_STR, (void*)&ioctlInfo);
  166.     if (err == kENODEVErr) {
  167.  
  168.         // Handle the case where there is no autopush information
  169.         // set for driverName by returning noErr.
  170.         
  171.         err = noErr;
  172.     }
  173.  
  174.     return err;
  175. }
  176.  
  177. //////////////////////////////////////////////////////////////////
  178. #pragma mark ----- Entry Points -----
  179.  
  180. extern pascal OSStatus ValidateModuleExists(const char *moduleName)
  181.     // See comment in interface part.
  182. {
  183.     OSStatus err;
  184.     StreamRef sadStream;
  185.     struct strioctl ioctlInfo;
  186.     struct str_list moduleInfo;
  187.     struct str_mlist oneModule[1];
  188.     
  189.     // Open a raw stream to "sad".
  190.     
  191.     sadStream = OTStreamOpen(kSADModuleName, 0, &err);
  192.     if (err != noErr) {
  193.         sadStream = nil;
  194.     }
  195.     
  196.     if (err == noErr) {
  197.     
  198.         // Fill out the oneModule structure.
  199.         
  200.         OTStrCopy(oneModule[0].l_name, moduleName);
  201.         
  202.         // Fill out the moduleInfo structure.
  203.  
  204.         moduleInfo.sl_nmods = 1;
  205.         moduleInfo.sl_modlist = oneModule;
  206.         
  207.         // Fill out the ioctl structure.
  208.         
  209.         ioctlInfo.ic_cmd = I_SAD_VML;
  210.         ioctlInfo.ic_dp     = (char *) &moduleInfo;
  211.         ioctlInfo.ic_len = sizeof(struct str_list);
  212.         ioctlInfo.ic_timout = INFTIM;
  213.         
  214.         // Call "sad".
  215.         
  216.         err = OTStreamIoctl(sadStream, I_STR, (void*)&ioctlInfo);
  217.         if (err != noErr) {
  218.         
  219.             // VML returns 1 if any of the modules do not exist.  We translate that
  220.             // to a kOTNotFoundErr, which makes more sense (-:
  221.             
  222.             err = kOTNotFoundErr;
  223.         }
  224.     }
  225.     if (sadStream != nil) {
  226.         (void) OTStreamClose(sadStream);
  227.     }
  228.     return err;
  229. }
  230.  
  231. extern pascal OSStatus GetAutoPushList(const char *driverName, OTAutopushInfo *autoPushInfo)
  232.     // See comment in interface part.
  233. {
  234.     OSStatus err;
  235.     OSStatus junk;
  236.     StreamRef sadStream;
  237.  
  238.     sadStream = OTStreamOpen(kSADModuleName, 0, &err);
  239.     if (err != noErr) {
  240.         sadStream = kOTInvalidStreamRef;
  241.     }
  242.     
  243.     // Get the current autopush list.
  244.     
  245.     if (err == noErr) {
  246.         err = SadGet(sadStream, autoPushInfo, driverName);
  247.     }
  248.  
  249.     if (sadStream != kOTInvalidStreamRef) {
  250.         junk = OTStreamClose(sadStream);
  251.         MoreAssertQ(junk == noErr);
  252.     }
  253.     return err;
  254. }
  255.  
  256. extern pascal OSStatus AddModuleToAutoPushList(const char *driverName, const char *moduleName)
  257.     // See comment in interface part.
  258. {
  259.     OSStatus err;
  260.     OSStatus junk;
  261.     StreamRef sadStream;
  262.     OTAutopushInfo autoPushInfo;
  263.     OTAutopushInfo origAutoPushInfo;
  264.  
  265.     sadStream = OTStreamOpen(kSADModuleName, 0, &err);
  266.     if (err != noErr) {
  267.         sadStream = kOTInvalidStreamRef;
  268.     }
  269.     
  270.     // Get the current autopush list.
  271.     
  272.     if (err == noErr) {
  273.         err = SadGet(sadStream, &autoPushInfo, driverName);
  274.     }
  275.  
  276.     // Add moduleName to the end of the list, and set it back.
  277.         
  278.     if (err == noErr) {
  279.         origAutoPushInfo = autoPushInfo;
  280.         if ( autoPushInfo.sap_npush == kOTAutopushMax ) {
  281.             err = kOTAddressBusyErr;
  282.         } else if ( FindModule(moduleName, &autoPushInfo) != -1 ) {
  283.             err = kEEXISTErr;
  284.         } else {
  285.             OTStrCopy(autoPushInfo.sap_list[autoPushInfo.sap_npush], moduleName);
  286.             autoPushInfo.sap_npush += 1;
  287.             
  288.             err = SadClear(sadStream, driverName);
  289.             if (err == noErr) {
  290.                 err = SadSet(sadStream, &autoPushInfo, driverName);
  291.                 if (err != noErr) {
  292.                     
  293.                     // We got an error setting the info, but we've already
  294.                     // cleared out the pre-existing information.  Better try
  295.                     // resetting it back to the original information we got.
  296.                     
  297.                     junk = SadClear(sadStream, driverName);
  298.                     MoreAssertQ(junk == noErr);
  299.                     junk = SadSet(sadStream, &origAutoPushInfo, driverName);
  300.                     MoreAssertQ(junk == noErr);
  301.                 }
  302.             }
  303.         }
  304.     }
  305.     if (sadStream != kOTInvalidStreamRef) {
  306.         junk = OTStreamClose(sadStream);
  307.         MoreAssertQ(junk == noErr);
  308.     }
  309.     return err;
  310. }
  311.  
  312. extern pascal OSStatus RemoveModuleDriverAutoPushList(const char *driverName, const char *moduleName)
  313.     // See comment in interface part.
  314. {
  315.     OSStatus err;
  316.     OSStatus junk;
  317.     StreamRef sadStream;
  318.     OTAutopushInfo autoPushInfo;
  319.     OTAutopushInfo origAutoPushInfo;
  320.     ItemCount moduleIndex;
  321.  
  322.     // Open a raw stream to "sad".
  323.     
  324.     sadStream = OTStreamOpen(kSADModuleName, 0, &err);
  325.     if (err != noErr) {
  326.         sadStream = kOTInvalidStreamRef;
  327.     }
  328.     
  329.     // Get the current autopush list.
  330.  
  331.     if (err == noErr) {
  332.         err = SadGet(sadStream, &autoPushInfo, driverName);
  333.     }
  334.  
  335.     // Search for moduleName in the list, and delete it.
  336.  
  337.     if (err == noErr) {
  338.         origAutoPushInfo = autoPushInfo;
  339.         moduleIndex = FindModule(moduleName, &autoPushInfo);
  340.         if (moduleIndex != -1) {
  341.             while ( moduleIndex < autoPushInfo.sap_npush ) {
  342.                 OTStrCopy(autoPushInfo.sap_list[moduleIndex],
  343.                             autoPushInfo.sap_list[moduleIndex + 1]);
  344.                 moduleIndex += 1;
  345.             }
  346.             autoPushInfo.sap_npush -= 1;
  347.         } else {
  348.             err = kENOENTErr;
  349.         }
  350.     }
  351.     
  352.     // Now write the new information back to "sad".
  353.     
  354.     if (err == noErr) {
  355.         err = SadClear(sadStream, driverName);
  356.         
  357.         // Only do this if there is some new information, otherwise
  358.         // "sad" will return an error.
  359.         
  360.         if (err == noErr && autoPushInfo.sap_npush > 0) {
  361.             err = SadSet(sadStream, &autoPushInfo, driverName);
  362.             if (err != noErr) {
  363.  
  364.                 // We got an error setting the info, but we've already
  365.                 // cleared out the pre-existing information.  Better try
  366.                 // resetting it back to the original information we got.
  367.  
  368.                 junk = SadClear(sadStream, driverName);
  369.                 MoreAssertQ(junk == noErr);
  370.                 junk = SadSet(sadStream, &origAutoPushInfo, driverName);
  371.                 MoreAssertQ(junk == noErr);
  372.             }
  373.         }
  374.     }
  375.     if (sadStream != kOTInvalidStreamRef) {
  376.         junk = OTStreamClose(sadStream);
  377.         MoreAssertQ(junk == noErr);
  378.     }
  379.     return err;
  380. }
  381.